<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\template\container;

interface ICss
{
  /**
   * Returns compiled template
   *
   * @return string
   */
  public function compile();
}

class ContainerCss implements ICss, IConcrete
{
  public function compile()
  {
    $this->parse();

    $sContent = '<?php $fExecuter = function(\crcl\base\template\Values $oValues) { ' .
      '$sContent =' . "\n" . '<<<BASE' . "\n";
    $sContent .= $this->sContent;
    $sContent .= xhtml\instructions\Concrete::endHeredoc() . 'return $sContent; } ?>';

    return $sContent;
  }

  public function setContent($sContent)
  {
    $this->sContent = $sContent;
    return $this;
  }

  /** PRIVATE *************************************************************************************/

  private $sContent = \NULL;

  private function parse()
  {
    $this->parseConstants();
    $this->parseAssets();
  }

  private function parseConstants()
  {
    $aConstants = array();
    if (\preg_match_all('#@constants\s*\{\s*([^\}]+)\s*\}\s*#i', $this->sContent, $aMatches))
    {
      foreach ($aMatches[0] as $iKey => $sConstant)
      {
        $this->sContent = str_replace($sConstant, '', $this->sContent);
        \preg_match_all('#([_a-z0-9]+)\s*:\s*([^;]+);#i', $aMatches[1][$iKey], $aVars);
        foreach ($aVars[1] as $sVar => $sName)
        {
          $aConstants["constant($sName)"] = $aVars[2][$sVar];
        }
      }
    }

    if (!empty($aConstants))
    {
      $this->sContent = \str_replace(\array_keys($aConstants), \array_values($aConstants),
        $this->sContent);
    }
  }

  private function parseAssets()
  {
    $sVersion = \crcl\base\Config::reader()->get('assets', 'version');
    $sRoot = \trim(\crcl\base\Config::reader()->get('assets', 'url'));
    $sRoot = \crcl\base\String::getInstance($sRoot)->doEndWith('/')->toString();

    $sRootFile = \crcl\base\application\Path::getDirectory(
        \crcl\base\application\Path::DIR_ASSETS_TEMPLATES);

    $sRootDefault = $sRoot . 'default/';
    $sRootFileDefault = $sRootFile . 'default/';
    if (\crcl\base\Mvc::hasTheme())
    {
      $sRoot .= \crcl\base\Mvc::getTheme() . '/';
      $sRootFile .= \crcl\base\Mvc::getTheme() . '/';
    }
    $aConstants = array();
    if (\preg_match_all('#@assets\s*\{\s*([^\}]+)\s*\}\s*#i', $this->sContent, $aMatches))
    {
      foreach ($aMatches[0] as $iKey => $sConstant)
      {
        $this->sContent = str_replace($sConstant, '', $this->sContent);
        \preg_match_all('#([_a-z0-9]+)\s*:\s*([^;]+);#i', $aMatches[1][$iKey], $aVars);
        foreach ($aVars[1] as $sVar => $sName)
        {
          if (file_exists($sRootFile . $aVars[2][$sVar]))
          {
            $aConstants["asset($sName)"] = $sRoot . $aVars[2][$sVar] . '?version=' . $sVersion;
          }
          else
          {
            $aConstants["asset($sName)"] = $sRootDefault . $aVars[2][$sVar] . '?version=' . $sVersion;
          }
        }
      }
    }

    if (!empty($aConstants))
    {
      $this->sContent = \str_replace(\array_keys($aConstants), \array_values($aConstants),
        $this->sContent);
    }
  }
}


//$css = trim(preg_replace('#/\*[^*]*\*+([^/*][^*]*\*+)*/#', '', $css)); // comments
//$css = preg_replace('#\s+(\{|\})#', "$1", $css); // before
//$css = preg_replace('#(\{|\}|:|,|;)\s+#', "$1", $css); // after

/* basedon
class BasedOnPlugin extends CacheerPlugin
{
function process($css)
{
  $bases = array();
  if (preg_match_all('#@base\(([^\s\{]+)\)\s*\{(\s*[^\}]+)\s*\}\s*#i', $css, $matches))
  {
    // For each declaration
    foreach ($matches[0] as $key => $base)
    {
      // Remove the @base declaration
      $css = str_replace($base, '', $css);

      // Add declaration to our array indexed by base name
      $bases[$matches[1][$key]] = $matches[2][$key];
    }

    // Parse nested based-on properties, stopping at circular references
    foreach ($bases as $base_name => $properties)
    {
      $bases[$base_name] = $this->replace_bases($bases, $properties, $base_name);
    }

    // Now apply replaced based-on properties in our CSS
    $css = $this->replace_bases($bases, $css);
  }

  return $css;
}

function replace_bases($bases, $css, $current_base_name = false)
{
  // As long as there's based-on properties in the CSS string
  // Get all instances
  while (preg_match_all('#\s*based-on:\s*base\(([^;]+)\);#i', $css, $matches))
  {
    // Loop through based-on instances
    foreach ($matches[0] as $key => $based_on)
    {
      $styles = '';
      $base_names = array();
      // Determine bases
      $base_names = preg_split('/[\s,]+/', $matches[1][$key]);
      // Loop through bases
      foreach ($base_names as $base_name)
      {
        // Looks like a circular reference, skip to next base
        if ($current_base_name && $base_name == $current_base_name)
        {
  */
  //        $styles .= '/* RECURSION */';
/*
            continue;
          }

          $styles .= $bases[$base_name];
        }

        // Insert styles this is based on
        $css = str_replace($based_on, $styles, $css);
      }
    }
    return $css;
  }
}*/
/*
class Base64Plugin extends CacheerPlugin
{
  function Base64Plugin()
  {
    if (isset($_SERVER['HTTP_USER_AGENT']))
    {
      $ua = $this->parse_user_agent($_SERVER['HTTP_USER_AGENT']);
      // Safari (WebKit), Firefox & Opera are known to support data: urls so embed base64-encoded images
      if
      (
        ($ua['browser'] == 'applewebkit' && $ua['version'] >= 125) || // Safari and ilk
        ($ua['browser'] == 'firefox') || // Firefox et al
        ($ua['browser'] == 'opera' && $ua['version'] >= 7.2) // quell vociferous Opera evangelists
      )
      {
        $this->flags['Base64'] = true;
      }
    }
  }

  function post_process($css)
  {
    if (isset($this->flags['Base64']))
    {
      global $requested_dir;
      $root_dir = $_SERVER['DOCUMENT_ROOT'];

      $images = array();
      if (preg_match_all('#url\(([^\)]+)\)#i', $css, $matches))
      {
        foreach($matches[1] as $relative_img)
        {
          if (!preg_match('#\.(gif|jpg|png)$#', $relative_img, $ext))
          {
            continue;
          }

          $images[$relative_img] = $ext[1];
        }

        foreach($images as $relative_img => $img_ext)
        {
          $up = substr_count($relative_img, '../');
          $absolute_img = $root_dir.preg_replace('#([^/]+/){'.$up.'}(\.\./){'.$up.'}#', '', $requested_dir.'/'.$relative_img);

          if (file_exists($absolute_img))
          {
            $img_raw = file_get_contents($absolute_img);
            $img_data = 'data:image/'.$img_ext.';base64,'.base64_encode($img_raw);
            $css = str_replace("url({$relative_img})", "url({$img_data})", $css);
          }
        }
      }
    }

    return $css;
  }

  // really simple (read: imperfect) rendering engine detection
  function parse_user_agent($user_agent)
  {
    $ua['browser']	= '';
    $ua['version']	= 0;

    if (preg_match('/(firefox|opera|applewebkit)(?: \(|\/|[^\/]*\/| )v?([0-9.]*)/i', $user_agent, $m))
    {
      $ua['browser']	= strtolower($m[1]);
      $ua['version']	= $m[2];
    }
    else if (preg_match('/MSIE ?([0-9.]*)/i', $user_agent, $v) && !preg_match('/(bot|(?<!mytotal)search|seeker)/i', $user_agent))
    {
      $ua['browser']	= 'ie';
      $ua['version']	= $v[1];
    }
    return $ua;
  }
}*/